home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / xmcd-1.4 / libdi.d / vu_chin.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-10  |  8.5 KB  |  388 lines

  1. /*
  2.  *   libdi - CD Audio Player Device Interface Library
  3.  *
  4.  *   Copyright (C) 1995  Ti Kan
  5.  *   E-mail: ti@amb.org
  6.  *
  7.  *   This program is free software; you can redistribute it and/or modify
  8.  *   it under the terms of the GNU General Public License as published by
  9.  *   the Free Software Foundation; either version 2 of the License, or
  10.  *   (at your option) any later version.
  11.  *
  12.  *   This program is distributed in the hope that it will be useful,
  13.  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  *   GNU General Public License for more details.
  16.  *
  17.  *   You should have received a copy of the GNU General Public License
  18.  *   along with this program; if not, write to the Free Software
  19.  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  *
  21.  *   This module supports the Chinon CDx-431 and CDx-435 CD-ROM drives.
  22.  *
  23.  *   The name "Chinon" is a trademark of Chinon Industries, and is
  24.  *   used here for identification purposes only.  This software and
  25.  *   its author are not affiliated in any way with Chinon.
  26.  *
  27.  */
  28. #ifndef LINT
  29. static char *_vu_chin_c_ident_ = "@(#)vu_chin.c    5.6 94/12/28";
  30. #endif
  31.  
  32. #include "common.d/appenv.h"
  33. #include "common.d/util.h"
  34. #include "libdi.d/libdi.h"
  35. #include "libdi.d/scsipt.h"
  36.  
  37. #ifdef VENDOR_CHINON
  38.  
  39. extern appdata_t    app_data;
  40. extern vu_tbl_t        scsipt_vutbl[];
  41.  
  42.  
  43. /*
  44.  * chin_playaudio
  45.  *    Play audio function: send vendor-unique play audio command
  46.  *    to the drive.
  47.  *
  48.  * Args:
  49.  *    addr_fmt - Flags indicating which address formats are passed in
  50.  *    If ADDR_BLK, then:
  51.  *        start_addr - The logical block starting address
  52.  *        end_addr - The logical block ending address
  53.  *    If ADD_MSF, then:
  54.  *        start_msf - Pointer to the starting MSF address structure
  55.  *        end_msf - Pointer to the ending MSF address structure
  56.  *    If ADDR_TRKIDX, then:
  57.  *        trk - The starting track number
  58.  *        idx - The starting index number
  59.  *    If ADDR_OPTEND, then the ending address, if specified, can be
  60.  *    ignored if possible.
  61.  *
  62.  * Return:
  63.  *    TRUE - success
  64.  *    FALSE - failure
  65.  */
  66. /*ARGSUSED*/
  67. bool_t
  68. chin_playaudio(
  69.     byte_t        addr_fmt,
  70.     word32_t    start_addr,
  71.     word32_t    end_addr,
  72.     msf_t        *start_msf,
  73.     msf_t        *end_msf,
  74.     byte_t        trk,
  75.     byte_t        idx
  76. )
  77. {
  78.     msf_t        istart_msf,
  79.             iend_msf;
  80.     curstat_t    *s = curstat_addr();
  81.     bool_t        ret = FALSE;
  82.  
  83.     /* Chinon only supports the Play Audio MSF command on the
  84.      * CDx-43x, which is identical to the SCSI-2 command of
  85.      * the same name and opcode.
  86.      */
  87.  
  88.     if (!ret && (addr_fmt & ADDR_BLK) && !(addr_fmt & ADDR_MSF)) {
  89.         /* Convert block address to MSF format */
  90.         blktomsf(
  91.             start_addr,
  92.             &istart_msf.min, &istart_msf.sec, &istart_msf.frame,
  93.             MSF_OFFSET(s)
  94.         );
  95.  
  96.         blktomsf(
  97.             end_addr,
  98.             &iend_msf.min, &iend_msf.sec, &iend_msf.frame,
  99.             MSF_OFFSET(s)
  100.         );
  101.  
  102.         /* Let the ADDR_MSF code handle the request */
  103.         start_msf = &istart_msf;
  104.         end_msf = &iend_msf;
  105.         addr_fmt |= ADDR_MSF;
  106.         ret = FALSE;
  107.     }
  108.  
  109.     if (!ret && (addr_fmt & ADDR_MSF))
  110.         ret = scsipt_playmsf(start_msf, end_msf);
  111.  
  112.     return (ret);
  113. }
  114.  
  115.  
  116. /*
  117.  * chin_start_stop
  118.  *      Start/stop function.
  119.  *
  120.  * Args:
  121.  *    start - TRUE: start unit, FALSE: stop unit
  122.  *    loej - TRUE: eject caddy, FALSE: do not eject
  123.  *
  124.  * Return:
  125.  *    TRUE - success
  126.  *    FALSE - failure
  127.  */
  128. bool_t
  129. chin_start_stop(bool_t start, bool_t loej)
  130. {
  131.     bool_t    ret;
  132.  
  133.     if (start)
  134.         /* Chinon CDx-43x does not support a start command so
  135.          * just quietly return success.
  136.          */
  137.         return TRUE;
  138.  
  139.     /* Stop the playback */
  140.     ret = pthru_send(OP_VC_STOP, 0, NULL, 0, 0, 0, 0, 0, READ_OP, TRUE);
  141.  
  142.     /* Eject the caddy if necessary */
  143.     if (ret && loej)
  144.         ret = pthru_send(OP_VC_EJECT, 0, NULL, 0, 0, 0, 0, 0,
  145.                  READ_OP, TRUE);
  146.  
  147.     return (ret);
  148. }
  149.  
  150.  
  151. /*
  152.  * chin_get_playstatus
  153.  *    Send vendor-unique command to obtain current audio playback
  154.  *    status.
  155.  *
  156.  * Args:
  157.  *    s - Pointer to the curstat_t structure
  158.  *    audio_status - Address where a current status code (SCSI-2
  159.  *               style) is to be returned.
  160.  *
  161.  * Return:
  162.  *    TRUE - success
  163.  *    FALSE - failure
  164.  */
  165. bool_t
  166. chin_get_playstatus(curstat_t *s, byte_t *audio_status)
  167. {
  168.     byte_t        buf[SZ_RDSUBQ],
  169.             *cp;
  170.     subq_hdr_t    *h;
  171.     subq_01_t    *p;
  172.  
  173.  
  174.     /* Chinon CDx-43x supports the Read Subchannel command which
  175.      * is identical to the SCSI-2 command of the same name and
  176.      * opcode, but the audio status codes are different.
  177.      */
  178.  
  179.     memset(buf, 0, sizeof(buf));
  180.  
  181.     if (!scsipt_rdsubq(buf, SUB_ALL, 1, 0, TRUE)) {
  182.         if (!di_check_disc(s))
  183.             /* Someone ejected the disc manually */
  184.             return FALSE;
  185.  
  186.         /* The read subchannel command failed for some
  187.          * unknown reason.  Just return success and
  188.          * hope the next poll succeeds.  We don't want
  189.          * to return FALSE here because that would stop
  190.          * the poll.
  191.          */
  192.         return TRUE;
  193.     }
  194.  
  195.     h = (subq_hdr_t *)(void *) buf;
  196.  
  197.     /* Translate Chinon audio status to SCSI-2 audio status */
  198.     switch (h->audio_status) {
  199.     case CAUD_PLAYING:
  200.         *audio_status = AUDIO_PLAYING;
  201.         break;
  202.     case CAUD_PAUSED:
  203.         *audio_status = AUDIO_PAUSED;
  204.         break;
  205.     case CAUD_INVALID:
  206.     default:
  207.         *audio_status = AUDIO_NOTVALID;
  208.         break;
  209.     }
  210.  
  211.     /* Check the subchannel data */
  212.     cp = (byte_t *) h + sizeof(subq_hdr_t);
  213.     switch (*cp) {
  214.     case SUB_ALL:
  215.     case SUB_CURPOS:
  216.         p = (subq_01_t *)(void *) cp;
  217.  
  218.         if (p->trkno != s->cur_trk) {
  219.             s->cur_trk = p->trkno;
  220.             dpy_track(s);
  221.         }
  222.  
  223.         if (p->idxno != s->cur_idx) {
  224.             s->cur_idx = p->idxno;
  225.             s->sav_iaddr = s->cur_tot_addr;
  226.             dpy_index(s);
  227.         }
  228.  
  229.         s->cur_tot_min = p->abs_addr.msf.min;
  230.         s->cur_tot_sec = p->abs_addr.msf.sec;
  231.         s->cur_tot_frame = p->abs_addr.msf.frame;
  232.         msftoblk(
  233.             s->cur_tot_min,
  234.             s->cur_tot_sec,
  235.             s->cur_tot_frame,
  236.             &s->cur_tot_addr,
  237.             MSF_OFFSET(s)
  238.         );
  239.  
  240.         s->cur_trk_min = p->rel_addr.msf.min;
  241.         s->cur_trk_sec = p->rel_addr.msf.sec;
  242.         s->cur_trk_frame = p->rel_addr.msf.frame;
  243.         msftoblk(
  244.             s->cur_trk_min,
  245.             s->cur_trk_sec,
  246.             s->cur_trk_frame,
  247.             &s->cur_trk_addr,
  248.             0
  249.         );
  250.  
  251.         break;
  252.     default:
  253.         /* Something is wrong with the data */
  254.         break;
  255.     }
  256.  
  257.     return TRUE;
  258. }
  259.  
  260.  
  261. /*
  262.  * chin_get_toc
  263.  *    Send vendor-unique command to obtain the disc table-of-contents
  264.  *
  265.  * Args:
  266.  *    s - Pointer to the curstat_t structure, which contains the TOC
  267.  *        table to be updated.
  268.  *
  269.  * Return:
  270.  *    TRUE - success
  271.  *    FALSE - failure
  272.  */
  273. bool_t
  274. chin_get_toc(curstat_t *s)
  275. {
  276.     int            i;
  277.     byte_t            buf[SZ_RDTOC],
  278.                 *cp,
  279.                 *toc_end;
  280.     bool_t            ret = FALSE;
  281.     toc_hdr_t        *h;
  282.     toc_trk_descr_t        *p;
  283.  
  284.  
  285.     /* Chinon CDx-43x supports the Read TOC command which is
  286.      * identical to the SCSI-2 command of the same name and opcode.
  287.      */
  288.  
  289.     memset(buf, 0, sizeof(buf));
  290.  
  291.     if (!scsipt_rdtoc(buf, TRUE, 0))
  292.         return FALSE;
  293.  
  294.     /* Fill curstat structure with TOC data */
  295.     h = (toc_hdr_t *)(void *) buf;
  296.     toc_end = (byte_t *) h + bswap16(h->data_len) + 2;
  297.  
  298.     s->first_trk = h->first_trk;
  299.     s->last_trk = h->last_trk;
  300.  
  301.     cp = (byte_t *) h + sizeof(toc_hdr_t);
  302.  
  303.     for (i = 0; cp < toc_end && i < MAXTRACK; i++) {
  304.         p = (toc_trk_descr_t *)(void *) cp;
  305.  
  306.         s->trkinfo[i].trkno = p->trkno;
  307.         s->trkinfo[i].type = (p->trktype == 0) ?
  308.             TYP_AUDIO : TYP_DATA;
  309.         s->trkinfo[i].min = p->abs_addr.msf.min;
  310.         s->trkinfo[i].sec = p->abs_addr.msf.sec;
  311.         s->trkinfo[i].frame = p->abs_addr.msf.frame;
  312.         msftoblk(
  313.             s->trkinfo[i].min,
  314.             s->trkinfo[i].sec,
  315.             s->trkinfo[i].frame,
  316.             &s->trkinfo[i].addr,
  317.             MSF_OFFSET(s)
  318.         );
  319.  
  320.         if (p->trkno == LEAD_OUT_TRACK ||
  321.             s->trkinfo[i-1].trkno == s->last_trk ||
  322.             i == (MAXTRACK - 1)) {
  323.             s->tot_min = s->trkinfo[i].min;
  324.             s->tot_sec = s->trkinfo[i].sec;
  325.             s->tot_frame = s->trkinfo[i].frame;
  326.             s->tot_trks = i;
  327.             s->tot_addr = s->trkinfo[i].addr;
  328.  
  329.             break;
  330.         }
  331.  
  332.         cp += sizeof(toc_trk_descr_t);
  333.     }
  334.  
  335.     return TRUE;
  336. }
  337.  
  338.  
  339. /*
  340.  * chin_eject
  341.  *    Send vendor-unique command to eject the caddy
  342.  *
  343.  * Args:
  344.  *    Nothing.
  345.  *
  346.  * Return:
  347.  *    TRUE - success
  348.  *    FALSE - failure
  349.  */
  350. bool_t
  351. chin_eject(void)
  352. {
  353.     return(pthru_send(OP_VC_EJECT, 0, NULL, 0, 0, 0, 0, 0, READ_OP, TRUE));
  354. }
  355.  
  356.  
  357. /*
  358.  * chin_init
  359.  *    Initialize the vendor-unique support module
  360.  *
  361.  * Args:
  362.  *    Nothing.
  363.  *
  364.  * Return:
  365.  *    Nothing.
  366.  */
  367. void
  368. chin_init(void)
  369. {
  370.     /* Register vendor_unique module entry points */
  371.     scsipt_vutbl[VENDOR_CHINON].vendor = "Chinon";
  372.     scsipt_vutbl[VENDOR_CHINON].playaudio = chin_playaudio;
  373.     scsipt_vutbl[VENDOR_CHINON].pause_resume = NULL;
  374.     scsipt_vutbl[VENDOR_CHINON].start_stop = chin_start_stop;
  375.     scsipt_vutbl[VENDOR_CHINON].get_playstatus = chin_get_playstatus;
  376.     scsipt_vutbl[VENDOR_CHINON].volume = NULL;
  377.     scsipt_vutbl[VENDOR_CHINON].route = NULL;
  378.     scsipt_vutbl[VENDOR_CHINON].mute = NULL;
  379.     scsipt_vutbl[VENDOR_CHINON].get_toc = chin_get_toc;
  380.     scsipt_vutbl[VENDOR_CHINON].eject = chin_eject;
  381.     scsipt_vutbl[VENDOR_CHINON].start = NULL;
  382.     scsipt_vutbl[VENDOR_CHINON].halt = NULL;
  383. }
  384.  
  385.  
  386. #endif    /* VENDOR_CHINON */
  387.  
  388.